Object.prototype.Inherits = function(parent)
{
	if(!parent || typeof(parent.call) != "function")
		return;
	if(arguments.length > 1)
		parent.apply(this, Array.prototype.slice.call(arguments,1));
	else
		parent.call(this);
}

Function.prototype.Inherits = function(parent)
{
	this.prototype = new parent();
	this.prototype.constructor = this;
}

function YHEngine()
{
	var Width = YHConstants.layout.width;
	this.getWidth = function() {
		return Width;
	};
	var Height = YHConstants.layout.height;
	this.getHeight = function() {
		return Height;
	};
	var Speed = YHConstants.speed;
	this.getSpeed = function() {
		return Speed;
	};
	this.setSpeed = function(val) {
		if(val)
			Speed = val;
		return this;
	};
	this.Scene = null;
	var Wrapper = null;
	this.getWrapper = function() {
		if(!this.Scene || this.Scene.Type == YHConstants.scene.mode.room)
			return this.getMainWrapper();
		else
			return this.Scene.getDivItem();
	};
	this.setWrapper = function(divWrapper){
		Wrapper = divWrapper;
		return this;
	};
	var MainWrapper = null;
	this.getMainWrapper = function() {
		if(!MainWrapper)
			MainWrapper = $('#wrapper');
		return MainWrapper;
	};
	this.Player = null;
	this.getWallHeight = function(){
		if(!this.Scene)
			return 0;
		return this.Scene.getWallHeight();
	};
	this.CanMove = function(item, x, y){
		var point = item.getActivePointFor(x, y);
		var center = item.getCenter();
		var itemCenter = this.getItemAt(center.X, center.Y, item);
		if((item == this.Player) && itemCenter && itemCenter.isAutoAction()){
			itemCenter.Action();
		}
		var result = this.CanBePlacedTo(item, point.X, point.Y) && this.CanBeInRoom(item, point.X, point.Y);
		var ItemsLength = this.ItemsInRoom.length;
		var itemIter = this.getItemAt(point.X, point.Y, item);
		if(itemIter) {
			if(typeof(itemIter.getWallLine) != "undefined" && itemIter.getWallLine()){
				itemIter.CheckVisibility(point.X, point.Y);
				if(itemIter.isCrossing(point.X, point.Y))
					return false;
			}
			else if(itemIter.isInside(point.X, point.Y) && !itemIter.isTransparent()){
				return false;
			}
		}else{
			item.goFrontForce();
			if(!this.Scene.isTransparent())
				return false;
		}
		return result;
	};
	this.getItemAt = function(x, y, item, condition){
		var selectedItem = null;
		var currZIndex = 0;
		var i = 0;
		var ItemsInRoomLength = this.ItemsInRoom.length;
		while(i < ItemsInRoomLength)
		{
			var itemIter = this.ItemsInRoom[i];
			i++;
			if(itemIter == item)
				continue;
			if(!itemIter.isVisible() || !itemIter.isInRect(x, y) || (condition && !condition(itemIter)))
				continue;
			var ZIndex = itemIter.getZIndex();
			if(ZIndex >= currZIndex)
				selectedItem = itemIter;
		}
		return selectedItem;
	};
	this.getItemByTitle = function(title) {
		var i = 0;
		var ItemsInRoomLength = this.ItemsInRoom.length;
		while(i < ItemsInRoomLength)
		{
			var itemIter = this.ItemsInRoom[i];
			i++;
			if(itemIter.getTitle() == title)
				return itemIter;
		}
		return null;
	
	};
	this.CanBeInRoom = function(item, x, y){
		if(this.Scene.Type != YHConstants.scene.mode.room)
			return true;
		return y >= this.Scene.getWallHeight();
	};
	this.CanBePlacedTo = function(item, x, y){
		var isPlayer = (item == this.Player);
		if(x <= 0)
		{
			if(isPlayer && this.Scene.getLeftLocation())
				this.NavigateTo(this.Scene.getLeftLocation(), this.Scene.getWidth() - YHConstants.scene.space, y);
			else
				return false;
		}
		if(item.getRight(x) - item.getWidth() >= this.Scene.getWidth())
		{
			if(isPlayer && this.Scene.getRightLocation())
				this.NavigateTo(this.Scene.getRightLocation(), YHConstants.scene.space, y);
			else
				return false;
		}
		if(y <= item.getHeight())
		{
			if(isPlayer && this.Scene.getTopLocation())
				this.NavigateTo(this.Scene.getTopLocation(), x, this.Scene.getHeight() - item.getHeightHalf() - YHConstants.scene.space);
			else
				return false;
		}
		if(item.getBottom(y) - item.getHeightHalf() >= this.Scene.getHeight())
		{
			if(isPlayer && this.Scene.getBottomLocation())
				this.NavigateTo(this.Scene.getBottomLocation(), x, item.getHeight());
			else
				return false;
		}
		return true;
	};
	this.ActionAt = function(point){
		if(!point)
			return false;
		var selectedItem = this.getItemAt(point.X, point.Y, this.Player, function(item) {
			return (typeof(item.Action) == "function");
		});
		if(selectedItem)
			selectedItem.Action();
		return true;
	};
	var regExpRoomPostfix = /.html(\?((x|y|item)=[\w\.]+&?)*)?/gi;
	this.NavigateTo = function(room, x, y){
		var roomPlace = room.replace(regExpRoomPostfix, "");
		var url = roomPlace + ".html?";
		if(x) url += "x=" + x + "&";
		if(y) url += "y=" + y + "&";
		location.href = url;
	};
	this.TeleportTo = function(room, itemTitle){
		var roomPlace = room.replace(regExpRoomPostfix, "");
		var url = roomPlace + ".html?";
		if(itemTitle) url += "item=" + itemTitle + "&";
		location.href = url;
	};
	this.ScrollX = function(newPos, dir) {
		var WrapperLeft = this.getWrapper().position().left;
		var WrapperWidth = this.getWrapper().width();
		var MainWrapperWidth = this.getMainWrapper().width();
		var MainWrapperWidthHalf = MainWrapperWidth / 2;
		var PlayerWidthHalf = this.Player.getWidth() / 2;
		if(dir == 'left' &&
			(WrapperLeft < 0 && WrapperWidth - newPos > MainWrapperWidthHalf + PlayerWidthHalf)){
			this.getWrapper().css('left', MainWrapperWidthHalf - newPos - PlayerWidthHalf);
		}
		else if((dir == 'right') &&
				(newPos + PlayerWidthHalf + WrapperLeft > MainWrapperWidthHalf && WrapperWidth - newPos - PlayerWidthHalf > MainWrapperWidthHalf)){
			this.getWrapper().css('left', MainWrapperWidthHalf - newPos - PlayerWidthHalf);
		}
		else if ((WrapperLeft == 0) &&(dir == 'right') && ((WrapperWidth - newPos) < MainWrapperWidthHalf)){
			this.getWrapper().css('left', MainWrapperWidth - WrapperWidth);
		}
		return this;
	};
	this.ScrollY = function(newPos, dir) {
		var WrapperTop = this.getWrapper().position().top;
		var WrapperHeight = this.getWrapper().height();
		var MainWrapperHeight = this.getMainWrapper().height();
		var MainWrapperHeightHalf = MainWrapperHeight / 2;
		var PlayerHeightHalf = this.Player.getHeight() / 2;
		if((dir == 'up') &&
			(WrapperHeight - newPos - PlayerHeightHalf > MainWrapperHeightHalf && newPos > MainWrapperHeightHalf)){
			YumeHikkiEngine.getWrapper().css('top', MainWrapperHeightHalf - newPos);
		}
		else if((dir == 'down') &&
				(WrapperHeight - newPos - PlayerHeightHalf > MainWrapperHeightHalf && newPos > MainWrapperHeightHalf)){
			YumeHikkiEngine.getWrapper().css('top', MainWrapperHeightHalf - newPos);
		}
		else if ((dir == 'down') && ((WrapperHeight - newPos - PlayerHeightHalf) < MainWrapperHeightHalf)){
			this.getWrapper().css('top', MainWrapperHeight - WrapperHeight + PlayerHeightHalf + 5);
		}
		return this;
	};
	this.PutPlayer = function(x, y){
		this.Player.setTop(y).setLeft(x);
		this.Player.Draw();
		if(this.Scene.Type == YHConstants.scene.mode.scene){
			this.ScrollX(x, 'right');
			this.ScrollY(y, 'down');
		}
		return this;
	};
	
	this.Win = function(index) {
		if(index && index < YHConstants.game.win.length)
			this.NavigateTo(YHConstants.game.win[index]);
		else
			this.NavigateTo(YHConstants.game.win[0]);
	};
	
	this.Die = function(index){
		if(index && index < YHConstants.game.end.length)
			this.NavigateTo(YHConstants.game.end[index]);
		else
			this.NavigateTo(YHConstants.game.end[0]);
	};
	this.ItemsInRoom = new Array();
	this.Events = new Array();
	this.Effects = new Array();
}


function YHLinkToScene(scene, x, y){
	var Scene = scene;
	this.getScene = function() {
		return Scene;
	};
	this.setScene = function(name) {
		Scene = name;
		return this;
	};
	var NavX = null;
	this.getX = function() {
		return NavX;
	};
	this.setX = function(num) {
		NavX = num;
		return this;
	};
	var NavY = null;
	this.getY = function() {
		return NavY;
	};
	this.setY = function(num) {
		NavY = num;
		return this;
	};
	var ItemTitle = null;
	this.getItemTitle = function() {
		return ItemTitle;
	};
	this.setItemTitle = function(itemTitle) {
		ItemTitle = itemTitle;
		return this;
	};
	this.isItemTitle = function() {
		return ItemTitle != null;
	};
	this.isItemCoord = function() {
		return (NavX != null) && (NavY != null);
	};
	if(x != null)
	{
		if(y != null)
		{
			NavX = x;
			NavY = y;
		}
		else
		{
			ItemTitle = x;
		}
	}
}

var YumeHikkiEngine = new YHEngine();

function YHEvent(func){
	this.DoEvent = (typeof(func) == "function") ? func : null;
	YumeHikkiEngine.Events.push(this);
}

function EventsTimer() {
	var EventsLength = YumeHikkiEngine.Events.length;
	var i = 0;
	while(i < EventsLength){
		var EventItem = YumeHikkiEngine.Events[i];
		i++;
		if(typeof(EventItem.DoEvent) == "function")
			EventItem.DoEvent();
	}
	t=setTimeout("EventsTimer()", YHConstants.events.time);
}

EventsTimer();